package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log/slog"
	"os"
	"path/filepath"
	"strings"
	"time"
)

func main() {
	// 解析命令行参数
	processType := flag.String("type", "", "处理类型: file(处理文本文件) 或 folder(处理文件夹)")
	flag.Parse()

	// 配置slog日志
	slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
		Level: slog.LevelInfo,
	})))

	// 检查是否提供了必要的参数
	if *processType == "" {
		fmt.Println("错误: 必须指定处理类型参数 -type")
		fmt.Println("用法: win-tools -type=file|folder")
		fmt.Println("  -type=file   处理桌面上'新建'开头的txt文本文件")
		fmt.Println("  -type=folder 处理桌面上'新建'开头的文件夹")
		return
	}

	// 获取桌面路径
	desktopPath, err := getDesktopPath()
	if err != nil {
		fmt.Printf("获取桌面路径失败: %v\n", err)
		return
	}

	// 生成时间戳
	timestamp := time.Now().Format("20060102_150405")

	// 根据处理类型执行不同的操作
	switch *processType {
	case "file":
		processTextFiles(desktopPath, timestamp)
	case "folder":
		processFolders(desktopPath, timestamp)
	default:
		fmt.Printf("未知的处理类型: %s, 请使用 file 或 folder\n", *processType)
	}
}

// 处理文本文件
func processTextFiles(desktopPath, timestamp string) {
	// 查找所有以"新建"开头的txt文件
	files, err := findTxtFiles(desktopPath)
	if err != nil {
		fmt.Printf("查找文件失败: %v\n", err)
		return
	}

	if len(files) == 0 {
		fmt.Println("未找到以'新建'开头的txt文件")
		return
	}

	// 使用slog记录找到的文件
	slog.Info("找到的文件列表", "文件数量", len(files))
	for i, file := range files {
		fileName := filepath.Base(file)
		slog.Info("文件", "序号", i+1, "文件名", fileName)
	}

	// 创建TMP文件夹
	tmpDir := filepath.Join(desktopPath, "TMP")
	err = ensureDirExists(tmpDir)
	if err != nil {
		fmt.Printf("创建TMP文件夹失败: %v\n", err)
		return
	}

	// 生成输出文件路径
	nameOutputPath := filepath.Join(tmpDir, fmt.Sprintf("TMP_NAME_%s.txt", timestamp))
	contentOutputPath := filepath.Join(tmpDir, fmt.Sprintf("TMP_TXT_%s.txt", timestamp))

	// 将文件名输出到TMP_NAME_{timestamp}.txt
	err = outputFileNames(files, nameOutputPath)
	if err != nil {
		fmt.Printf("输出文件名失败: %v\n", err)
		return
	}

	// 读取并合并文件内容
	content, err := mergeFileContents(files)
	if err != nil {
		fmt.Printf("合并文件内容失败: %v\n", err)
		return
	}

	// 写入到TMP_TXT_{timestamp}.txt文件
	err = ioutil.WriteFile(contentOutputPath, []byte(content), 0644)
	if err != nil {
		fmt.Printf("写入输出文件失败: %v\n", err)
		return
	}

	fmt.Printf("成功合并 %d 个文件到 %s\n", len(files), contentOutputPath)
	fmt.Printf("成功将 %d 个文件名输出到 %s\n", len(files), nameOutputPath)

	// 直接删除已处理的文件
	deletedCount, err := deleteFiles(files)
	if err != nil {
		fmt.Printf("删除文件失败: %v\n", err)
	} else {
		fmt.Printf("成功删除 %d 个文件\n", deletedCount)
	}
}

// 处理文件夹
func processFolders(desktopPath, timestamp string) {
	// 查找所有以"新建"开头的文件夹
	folders, err := findFolders(desktopPath)
	if err != nil {
		fmt.Printf("查找文件夹失败: %v\n", err)
		return
	}

	if len(folders) == 0 {
		fmt.Println("未找到以'新建'开头的文件夹")
		return
	}

	// 使用slog记录找到的文件夹
	slog.Info("找到的文件夹列表", "文件夹数量", len(folders))
	for i, folder := range folders {
		folderName := filepath.Base(folder)
		slog.Info("文件夹", "序号", i+1, "文件夹名", folderName)
	}

	// 创建TMP文件夹
	tmpDir := filepath.Join(desktopPath, "TMP")
	err = ensureDirExists(tmpDir)
	if err != nil {
		fmt.Printf("创建TMP文件夹失败: %v\n", err)
		return
	}

	// 创建带时间戳的目标文件夹
	targetDir := filepath.Join(tmpDir, fmt.Sprintf("TMP_%s", timestamp))
	err = ensureDirExists(targetDir)
	if err != nil {
		fmt.Printf("创建目标文件夹失败: %v\n", err)
		return
	}

	// 移动文件夹到目标文件夹
	movedCount, err := moveFolders(folders, targetDir)
	if err != nil {
		fmt.Printf("移动文件夹失败: %v\n", err)
	} else {
		fmt.Printf("成功移动 %d 个文件夹到 %s\n", movedCount, targetDir)
	}
}

// 查找所有以"新建"开头的文件夹
func findFolders(desktopPath string) ([]string, error) {
	var folders []string

	files, err := ioutil.ReadDir(desktopPath)
	if err != nil {
		return nil, err
	}

	for _, file := range files {
		if file.IsDir() && strings.HasPrefix(file.Name(), "新建") {
			folders = append(folders, filepath.Join(desktopPath, file.Name()))
		}
	}

	return folders, nil
}

// 移动文件夹到目标文件夹
func moveFolders(folders []string, targetDir string) (int, error) {
	movedCount := 0

	for _, folder := range folders {
		folderName := filepath.Base(folder)
		destPath := filepath.Join(targetDir, folderName)

		// 如果目标路径已存在，添加序号
		if _, err := os.Stat(destPath); err == nil {
			for i := 1; ; i++ {
				newDestPath := fmt.Sprintf("%s_%d", destPath, i)
				if _, err := os.Stat(newDestPath); os.IsNotExist(err) {
					destPath = newDestPath
					break
				}
			}
		}

		// 移动文件夹
		err := os.Rename(folder, destPath)
		if err != nil {
			slog.Error("移动文件夹失败",
				"文件夹", folder,
				"错误", err)
			continue
		}

		movedCount++
		slog.Info("已移动文件夹", "文件夹", folderName, "目标路径", destPath)
	}

	return movedCount, nil
}

// 确保目录存在，如果不存在则创建
func ensureDirExists(dirPath string) error {
	if _, err := os.Stat(dirPath); os.IsNotExist(err) {
		return os.MkdirAll(dirPath, 0755)
	}
	return nil
}

// 获取桌面路径
func getDesktopPath() (string, error) {
	// 在Windows系统中获取桌面路径
	userProfile := os.Getenv("USERPROFILE")
	if userProfile == "" {
		return "", fmt.Errorf("无法获取用户配置文件路径")
	}
	return filepath.Join(userProfile, "Desktop"), nil
}

// 查找所有以"新建"开头的txt文件
func findTxtFiles(desktopPath string) ([]string, error) {
	var files []string

	err := filepath.Walk(desktopPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		// 检查是否是文件，是否以"新建"开头，是否以.txt结尾
		if !info.IsDir() &&
			strings.HasPrefix(filepath.Base(path), "新建") &&
			strings.HasSuffix(strings.ToLower(path), ".txt") {
			files = append(files, path)
		}
		return nil
	})

	if err != nil {
		return nil, err
	}
	return files, nil
}

// 输出文件名到指定路径
func outputFileNames(files []string, outputPath string) error {
	var fileNames strings.Builder

	fileNames.WriteString(fmt.Sprintf("找到 %d 个文件：\n\n", len(files)))

	for i, file := range files {
		fileName := filepath.Base(file)
		fileNames.WriteString(fmt.Sprintf("%d. %s\n", i+1, fileName))
	}

	return ioutil.WriteFile(outputPath, []byte(fileNames.String()), 0644)
}

// 读取并合并文件内容
func mergeFileContents(files []string) (string, error) {
	var allContent strings.Builder

	for _, file := range files {
		content, err := ioutil.ReadFile(file)
		if err != nil {
			return "", fmt.Errorf("读取文件 %s 失败: %v", file, err)
		}

		fileName := filepath.Base(file)
		allContent.WriteString(fmt.Sprintf("=== 文件: %s ===\n", fileName))
		allContent.Write(content)
		allContent.WriteString("\n\n")
	}

	return allContent.String(), nil
}

// 直接删除文件
func deleteFiles(files []string) (int, error) {
	deletedCount := 0

	for _, file := range files {
		err := os.Remove(file)
		if err != nil {
			slog.Error("删除文件失败",
				"文件", file,
				"错误", err)
			continue
		}

		deletedCount++
		slog.Info("已删除文件", "文件", filepath.Base(file))
	}

	return deletedCount, nil
}
